package com.charm.bulkcomponent

import android.graphics.Bitmap
import android.graphics.PixelFormat
import android.os.Bundle
import android.support.v7.app.AppCompatActivity
import android.view.ViewGroup
import android.widget.ImageView
import com.afollestad.materialdialogs.MaterialDialog
import com.alibaba.android.arouter.facade.annotation.Route
import com.charm.codes.R
import com.charm.codes.widget.dialog.LoadingDialogHelper
import com.tencent.smtt.sdk.WebChromeClient
import com.tencent.smtt.sdk.WebSettings
import com.tencent.smtt.sdk.WebView
import com.tencent.smtt.sdk.WebViewClient
import com.charm.bulkcomponent.vassonic.SonicSessionClientImpl
import android.content.Intent
import com.charm.bulkcomponent.vassonic.HostSonicRuntime
import com.charm.bulkcomponent.vassonic.OfflinePkgSessionConnection
import com.tencent.smtt.export.external.interfaces.WebResourceRequest
import com.tencent.smtt.export.external.interfaces.WebResourceResponse
import com.tencent.sonic.sdk.*


/**
 * Created by tools on 2018/1/25.
 */
@Route(path = "/common/browser/activity")
class BrowserActivity : AppCompatActivity() {
    internal lateinit var mIntentUrl: String
    internal lateinit var mViewParent: ViewGroup
    internal lateinit var mWebView: WebView
    internal var loadingDialog: MaterialDialog? = null
    internal lateinit var actionBack: ImageView
    internal lateinit var actionClose: ImageView
    val PARAM_URL = "param_url"
    val PARAM_MODE = "param_mode"
    val MODE_DEFAULT = 0
    val MODE_SONIC = 1
    val MODE_SONIC_WITH_OFFLINE_CACHE = 2
    var sonicSession: SonicSession? = null
    private val PERMISSION_REQUEST_CODE_STORAGE = 1
    var mode: Int = 1
    var sonicSessionClient: SonicSessionClientImpl? = null
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        before()
        initVasSonic()
        setContentView(R.layout.activity_browser)
        initView()
        initListener()
        initData()
    }

    private fun initVasSonic() {
        if (!SonicEngine.isGetInstanceAllowed()) {
            SonicEngine.createInstance(HostSonicRuntime(application), SonicConfig.Builder().build())
        }

        // if it's sonic mode , startup sonic session at first time
        if (MODE_DEFAULT !== mode) { // sonic mode
            val sessionConfigBuilder = SonicSessionConfig.Builder()
            sessionConfigBuilder.setSupportLocalServer(true)

            // if it's offline pkg mode, we need to intercept the session connection
            if (MODE_SONIC_WITH_OFFLINE_CACHE === mode) {
                sessionConfigBuilder.setCacheInterceptor(object : SonicCacheInterceptor(null) {
                    override fun getCacheData(session: SonicSession): String? {
                        return null // offline pkg does not need cache
                    }
                })
                sessionConfigBuilder.setConnectionInterceptor(object : SonicSessionConnectionInterceptor() {
                    override fun getConnection(session: SonicSession, intent: Intent): SonicSessionConnection {
                        return OfflinePkgSessionConnection(this@BrowserActivity, session, intent)
                    }
                })
            }

            // create sonic session and run sonic flow
            sonicSession = SonicEngine.getInstance().createSession(mIntentUrl, sessionConfigBuilder.build())
            if (null != sonicSession) {
                sonicSessionClient = SonicSessionClientImpl()
                sonicSession!!.bindClient(sonicSessionClient)
            } else {
                // this only happen when a same sonic session is already running,
                // u can comment following codes to feedback as a default mode.
                // throw new UnknownError("create session fail!");
//                Toast.makeText(this, "create sonic session fail!", Toast.LENGTH_LONG).show()
            }
        }
    }

    private fun before() {
        window.setFormat(PixelFormat.TRANSLUCENT)
        val intent = intent
        if (intent != null) {
            try {
                mIntentUrl = intent.extras!!.getString("url")
            } catch (e: NullPointerException) {

            } catch (e: Exception) {
            }

        }
        try {
            if (Integer.parseInt(android.os.Build.VERSION.SDK) >= 11) {
                window
                        .setFlags(
                                android.view.WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED,
                                android.view.WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED)
            }
        } catch (e: Exception) {
        }

    }


    private fun initView() {
        actionBack = findViewById(R.id.action_back)
        actionClose = findViewById(R.id.action_close)
        mWebView = findViewById(R.id.webView)
        initWebViewSettings()
    }

    private fun initData() {
        if (mIntentUrl == null) {
            return
        }
        if (sonicSessionClient != null) {
            sonicSessionClient!!.bindWebView(mWebView)
            sonicSessionClient!!.clientReady()
        } else { // default mode
            mWebView.loadUrl(mIntentUrl)
        }
    }

    private fun initListener() {
        mWebView.webViewClient = object : WebViewClient() {
            override fun shouldInterceptRequest(p0: WebView?, p1: String?): WebResourceResponse? {
                return if (sonicSession != null) {
                    sonicSession!!.sessionClient.requestResource(p1) as WebResourceResponse
                } else null
            }

//            override fun shouldInterceptRequest(p0: WebView?, p1: WebResourceRequest?): WebResourceResponse? {
//                var t = p1!!.requestHeaders["Referer"]
//                return shouldInterceptRequest(p0, t)
//            }

            override fun shouldOverrideUrlLoading(view: WebView?, url: String?): Boolean {
                view!!.loadUrl(url)
                return super.shouldOverrideUrlLoading(view, url)
            }


            override fun onPageFinished(view: WebView?, url: String?) {
                super.onPageFinished(view, url)
                if (sonicSession != null) {
                    sonicSession!!.sessionClient.pageFinish(url)
                }
                dismissLoadingDialog()
            }

            override fun onPageStarted(p0: WebView?, p1: String?, p2: Bitmap?) {
                super.onPageStarted(p0, p1, p2)
                showLoadingDialog()
            }
        }
        mWebView.webChromeClient = object : WebChromeClient() {}


        actionClose.setOnClickListener {
            finish()
        }

        actionBack.setOnClickListener {
            if (mWebView.canGoBack()) {
                mWebView.goBack()
            } else {
                finish()
            }
        }

    }

    private fun initWebViewSettings() {
        val webSetting = mWebView.settings
        webSetting.javaScriptEnabled = true
        webSetting.javaScriptCanOpenWindowsAutomatically = true
        webSetting.allowFileAccess = true
        webSetting.layoutAlgorithm = WebSettings.LayoutAlgorithm.NARROW_COLUMNS
        webSetting.setSupportZoom(true)
        webSetting.builtInZoomControls = true
        webSetting.useWideViewPort = true
        webSetting.setSupportMultipleWindows(true)
        webSetting.setAppCacheEnabled(true)
        webSetting.domStorageEnabled = true
        webSetting.setGeolocationEnabled(true)
        webSetting.setAppCacheMaxSize(java.lang.Long.MAX_VALUE)
        webSetting.pluginState = WebSettings.PluginState.ON_DEMAND
        webSetting.cacheMode = WebSettings.LOAD_NO_CACHE
    }

    private fun dismissLoadingDialog() {
        if (loadingDialog == null) {
            return
        }
        if (!loadingDialog!!.isShowing) {
            return
        }
        loadingDialog!!.dismiss()
    }

    private fun showLoadingDialog() {
        if (loadingDialog == null) {
            loadingDialog = LoadingDialogHelper.getLoadingDialog(this)
        }
        if (loadingDialog!!.isShowing) {
            return
        }
        loadingDialog!!.show()
    }

    override fun finish() {
        dismissLoadingDialog()
        super.finish()
    }
}